global class EmailVelocityHandler
{
    global void EmailVelocityHandler() {}
 
    
    public class Hist
    {
        public String toAddress;
        public String fromAddress;
        public Integer cnt;
    }
    
    public Boolean checkIgnores(String fromAddy, String toAddy, Integer cnt, List<EmailVelocityIgnore__c> items)
    {
        for (EmailVelocityIgnore__c item : items)
        {
            if ((item.ToAddress__c.equalsIgnoreCase(toAddy)) && (item.FromAddress__c.equalsIgnoreCase(fromAddy)))
            {
                 if (cnt > item.Threshold__c)
                    return True;
                 else
                    return False;
            }
        }
        return True;  
    }
    
     
    public List<EmailVelocityHandler.Hist> handle(Integer window, Integer thresh)
    {
        Integer cnt;
        Map<String, Integer> emailCount = new Map<String, Integer>();
        DateTime windowDT = System.now().addMinutes(-window);
        List<EmailMessage> Msgs = [Select Id, ParentId, MessageDate, ToAddress, fromAddress From EmailMessage where MessageDate >= :windowDT order by MessageDate desc];
        List<EmailVelocityHandler.Hist> Offenders = new List<EmailVelocityHandler.Hist>();
        // compute a "histogram" of the {case ID, toAddress} combo
        for (EmailMessage email : Msgs)
        {
            String key = email.fromAddress + ':' + email.toAddress;
            
            cnt = emailCount.get(key);
            if (cnt != null)
            {
                emailCount.put(key, cnt+1);
            }
            else
            {
                emailCount.put(key, 1);
            }
        }
    
        List<EmailVelocityIgnore__c> ignores = EmailVelocityIgnoreHandler.getActive();
        Set<String> keys = emailCount.keySet();
                           
        for (String key : keys)
        {
            String[] b = key.split(':',0);
            cnt = emailCount.get(key);
            
            // if the count doesn't pass the thresh, don't add it, otherwise need to check if it
            // is on the ignore list, and if so, if the count surpasses the seperate thresh for that item.
            if (cnt >= thresh)
            {
                if (checkIgnores(b[1], b[0], cnt, ignores))
                {
                    Hist item = new Hist();
                    item.toAddress = b[0];
                    item.fromAddress = b[1];
                    item.cnt = cnt;
                    Offenders.add(item);
                }
            }
        }
        return Offenders;        
    }  
}